home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / ugly / args_set.c < prev    next >
C/C++ Source or Header  |  1996-11-17  |  20KB  |  797 lines

  1. /*
  2.  * ugly/args_set.c
  3.  *
  4.  * ugly set arguments handling functions
  5.  *
  6.  * Copyright (C) 1994,95,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 17-Nov-1996
  23.  * created:  3-Jul-1994
  24.  *
  25.  *===================================================================
  26.  * TODO:
  27.  * - support ARG_LONG_RANGE
  28.  * - support ARG_INV_SWITCH (set switch value to FALSE if NOxxx found)
  29.  *
  30.  */
  31.  
  32. /*
  33.  * includes
  34.  */
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <stdarg.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40.  
  41. #include "utypes.h"
  42. #include "ufile.h"
  43. #include "umemory.h"
  44. #include "ustring.h"
  45. #include "dllist.h"
  46.  
  47. #define NOEXTERN_UGLY_UARGS_H
  48. #include "uargs.h"
  49.  
  50. #if 0
  51. #undef DA
  52. #define DA(x) x
  53. #endif
  54.  
  55. /*
  56.  * global export vars
  57.  */
  58. static int arg_error_num = -1;  /* error number */
  59. static STRPTR arg_error_arg = NULL;     /* argument causing error */
  60. static STRPTR arg_error_hfs = NULL;     /* error string returned by handle function */
  61.  
  62. /*
  63.  * result string for _strargerr()
  64.  */
  65. #define SIZE_ARGERRSTR 60
  66. static STRARR argerrstr[SIZE_ARGERRSTR];
  67.  
  68. /*
  69.  * local global vars
  70.  */
  71. static BOOL no_argerr = TRUE;   /* error flags for _set_args() */
  72. static BOOL any_argerr = FALSE;
  73. static int argidx = -1;         /* index in _argv[] currently examing */
  74.  
  75. /*
  76.  * compare_arginfo
  77.  *   ( called by _set_args() )
  78.  *
  79.  */
  80. static int compare_arginfo(APTR cmp_data, APTR list_data)
  81. {
  82.     struct arginfo *ai = (struct arginfo *) list_data;
  83.     STRPTR lst_arg = strclone(ai->ai_id);       /* TODO: possible enforcer hit */
  84.     STRPTR cmp_arg = ((struct arginfo *) cmp_data)->ai_id;      /* TODO: possible enforcer hit */
  85.     BOOL eq = FALSE;
  86.     char lastch;
  87.  
  88.     if (lst_arg && cmp_arg)
  89.     {
  90.         STRPTR nxt_arg = strtok(lst_arg, "=");
  91.  
  92.         while (nxt_arg && (eq == FALSE))
  93.         {
  94.             if (ai->ai_flags & ARG_CASESENS)
  95.             {
  96.                 eq = (strncmp(nxt_arg, cmp_arg, strlen(nxt_arg)) == 0);
  97.             }
  98.             else
  99.             {
  100.                 eq = (upstrncmp(nxt_arg, cmp_arg, strlen(nxt_arg)) == 0);
  101.             }
  102.  
  103. #if 0
  104.             if (eq)
  105.             {
  106.                 if (ai->ai_type != ARG_SWITCH)
  107.                     eq = (cmp_arg[strlen(nxt_arg)] == '=');
  108.             }
  109. #endif
  110.             lastch = cmp_arg[strlen(nxt_arg)];
  111.             eq &= (lastch == '\0') || (lastch == '=');
  112.  
  113.             nxt_arg = strtok(NULL, "=");
  114.         }                       /* while */
  115.  
  116.     }
  117.     else
  118.     {
  119.         eq = FALSE;
  120.     }
  121.  
  122.     ufreestr(lst_arg);
  123.  
  124.     return eq;
  125. }
  126.  
  127. /*
  128.  * clr_ai_set
  129.  *
  130.  * clear all ai_set bits in all _arginfo entries of an _arglist
  131.  *
  132.  */
  133. static VOID clr_ai_set(ARGLIST * al)
  134. {
  135. #if 0
  136.     struct dlnode *nd;
  137.     struct arginfo *ai;
  138.  
  139.     if (al)
  140.         if (al->al_list)
  141.             if (nd = al->al_list->first)
  142.                 while (nd)
  143.                 {
  144.  
  145.                     if (ai = (struct arginfo *) nd->data)
  146.                         ai->ai_set = FALSE;
  147.                     nd = nd->next;
  148.  
  149.                 }
  150. #endif
  151.     if (al && (al->al_list))
  152.     {
  153.         struct dlnode *nd = al->al_list->first;
  154.  
  155.         while (nd)
  156.         {
  157.             struct arginfo *ai = (struct arginfo *) nd->data;
  158.  
  159.             if (ai)
  160.                 ai->ai_set = FALSE;
  161.             nd = nd->next;
  162.         }
  163.     }
  164. }
  165.  
  166. /*
  167.  * reset_nokeywd
  168.  *
  169.  * set al_nokeywd to first entry w/o ARG_KEYWORD flag
  170.  *
  171.  */
  172. static VOID reset_nokeywd(ARGLIST * al)
  173. {
  174.     /*
  175.      * NOTE: _al must be fully initialised _arglist,
  176.      *       otherwise _set_args() would have rejeceted
  177.      *       it. therefor no "al == NULL" check is done
  178.      *       when setting _nd and _ai.
  179.      */
  180.     struct dlnode *nd = al->al_list->first;
  181.     struct arginfo *ai = (struct arginfo *) nd->data;
  182.  
  183.     if (ai->ai_flags & ARG_KEYWORD || (ai->ai_type == ARG_SWITCH))
  184.     {
  185.         al->al_nokeywd = NULL;
  186.  
  187.         do
  188.         {
  189.             if ((ai->ai_flags & ARG_KEYWORD)
  190.                 || (ai->ai_type == ARG_SWITCH))
  191.             {
  192.                 nd = nd->next;
  193.                 if (nd)
  194.                     ai = (struct arginfo *) nd->data;
  195.             }
  196.             else
  197.                 al->al_nokeywd = ai;
  198.         }
  199.         while (nd && !(al->al_nokeywd));
  200.     }
  201.     else
  202.     {
  203.         al->al_nokeywd = ai;
  204.     }
  205. }
  206.  
  207. /*
  208.  * find_nxt_nokeywd
  209.  *
  210.  * find next entry w/o ARG_KEYWORD flag set
  211.  *
  212.  */
  213. static VOID find_nxt_nokeywd(ARGLIST * al)
  214. {
  215.     if (al->al_nokeywd)
  216.     {
  217. #if 0
  218.         /*
  219.          * find entry in al_list pointing to al_nokeywd
  220.          */
  221.         struct dlnode *nd = al->al_list->first;
  222.         struct arginfo *ai;
  223.  
  224.         while (al->al_nokeywd != (struct arginfo *) nd->data)
  225.             nd = nd->next;
  226.  
  227.         /*
  228.          * find next entry in al_list w/o ARG_KEYWORD
  229.          */
  230.         nd = nd->next;
  231.         al->al_nokeywd = NULL;
  232.         while (nd && (al->al_nokeywd == NULL))
  233.         {
  234.             ai = (struct arginfo *) nd->data;
  235.  
  236.             if ((ai->ai_flags & ARG_KEYWORD)
  237.                 || (ai->ai_type == ARG_SWITCH)
  238.                 )
  239.                 nd = nd->next;
  240.             else
  241.                 al->al_nokeywd = ai;
  242.         };
  243. #endif
  244.         /*
  245.          * find entry in al_list pointing to al_nokeywd
  246.          */
  247.         struct dlnode *nd = al->al_list->first;
  248.         struct arginfo *ai;
  249.  
  250.         /*
  251.          * find next entry in al_list w/o ARG_KEYWORD
  252.          */
  253.         al->al_nokeywd = NULL;
  254.         while (nd && (al->al_nokeywd == NULL))
  255.         {
  256.             BOOL is_keywd = FALSE;
  257.             BOOL multiple_nokeywd = FALSE;
  258.  
  259.             ai = (struct arginfo *) nd->data;
  260.  
  261.             is_keywd = ai->ai_flags & ARG_KEYWORD;
  262.             multiple_nokeywd =
  263.                 (ai->ai_flags & ARG_MULTIPLE)
  264.                 && !is_keywd;
  265.  
  266.             if (((ai->ai_flags & ARG_KEYWORD)
  267.                  || (ai->ai_type == ARG_SWITCH)
  268.                  || (ai->ai_set))
  269.                 && !multiple_nokeywd)
  270.             {
  271.                 nd = nd->next;
  272.             }
  273.             else
  274.             {
  275.                 al->al_nokeywd = ai;
  276.             }
  277.         }
  278.     }
  279. }
  280.  
  281. /*
  282.  *
  283.  * error functions for _set_args()
  284.  *
  285.  */
  286. static VOID set_argerr(int num, STRPTR arg)
  287. {
  288.     if (no_argerr)
  289.     {
  290.         no_argerr = FALSE;
  291.         any_argerr = TRUE;
  292.  
  293.         arg_error_num = num;
  294.         arg_error_arg = arg;
  295.     }
  296. }
  297.  
  298. static VOID clr_argerr(VOID)
  299. {
  300.     no_argerr = TRUE;
  301.     any_argerr = FALSE;
  302.     arg_error_num = 0;
  303.     arg_error_arg = NULL;
  304. }
  305.  
  306. /*
  307.  * strargerr
  308.  *
  309.  * returns string containing detailed error message of
  310.  * error occured in last call of _set_args()
  311.  *
  312.  */
  313. STRPTR strargerr(VOID)
  314. {
  315.     STRPTR str = "unknown error";
  316.  
  317.     switch (arg_error_num)
  318.     {
  319.     case ASE_NO_MEM:
  320.         str = "out of memory";
  321.         break;
  322.  
  323.     case ASE_OCCURED_TWICE:
  324.         str = "argument occured twice";
  325.         break;
  326.  
  327.     case ASE_UNKNOWN_KEYWORD:
  328.         str = "unknown keyword";
  329.         break;
  330.  
  331.     case ASE_INVALID_NUM:
  332.         str = "invalid numeric argument";
  333.         break;
  334.  
  335.     case ASE_INVALID_ENUM:
  336.         str = "invalid enumerator value";
  337.         break;
  338.  
  339.     case ASE_REQUIRED_MISS:
  340.         str = "required argument missing";
  341.         break;
  342.  
  343.     case ASE_EMPTY_TEMPLATE:
  344.         str = "empty template";
  345.         break;
  346.  
  347.     case ASE_OUT_OF_RANGE:
  348.         str = "numeric argument out of range";
  349.         break;
  350.     case ASE_NO_VAL_AFTER_KW:
  351.         str = "value after keyword missing";
  352.         break;
  353.  
  354.     case ASE_HANDLE_FUNC:       /* error in handle function */
  355.         str = arg_error_hfs;
  356.         break;
  357.     }                           /* switch */
  358.  
  359.     strcpy(argerrstr, str);
  360.     if (arg_error_arg)
  361.     {
  362.         strncat(argerrstr, ": ", SIZE_ARGERRSTR - strlen(str) - 1);
  363.         strncat(argerrstr, arg_error_arg, SIZE_ARGERRSTR - strlen(str) - 3);
  364.     }
  365.  
  366.     if (arg_error_num)
  367.         return argerrstr;
  368.     else
  369.         return NULL;
  370. }
  371.  
  372. /*
  373.  * pargerr
  374.  *
  375.  * printf error message from last call of _set_args()
  376.  *
  377.  */
  378. VOID pargerr(VOID)
  379. {
  380.     if (arg_error_num)
  381.         fprintf(stderr, "%s\n", strargerr());
  382. }
  383.  
  384. /*
  385.  * set_arg_value
  386.  *
  387.  * sets argument _ai->ai_dest with value specified in _arg
  388.  *
  389.  */
  390. static UBYTE set_arg_value(struct arginfo *ai, STRPTR arg, STRPTR arg2, BOOL keywd)
  391. {
  392.     APTR dest = ai->ai_dest;
  393.     STRPTR param;
  394.     UBYTE arg_incr = 0;         /* set to 1 if arg2 is used */
  395.     BOOL arg2used = FALSE;
  396.  
  397.     /* evaluate parameter:                                 */
  398.     /*   if arg is equal to arg-id of ai (no other chars   */
  399.     /*   following), the param is taken from the next arg. */
  400.     /*   otherwise, the arg is scanned for '=' and the     */
  401.     /*   rest of the arg is taken as param                 */
  402.     if (keywd && !(ai->ai_type == ARG_SWITCH))
  403.     {
  404.         param = arg;
  405.         while (param[0] && (param[0] != '='))
  406.             param++;
  407.         if (param[0])
  408.             param++;
  409.         else
  410.         {
  411.             param = arg2;
  412.             arg2used = TRUE;
  413.             if (!param)
  414.                 set_argerr(ASE_REQUIRED_MISS, arg);
  415.         }
  416.     }
  417.     else
  418.         param = arg;
  419.  
  420.     /*
  421.      * set switch/arg-value
  422.      */
  423.     if (no_argerr)
  424.     {
  425.         if (ai->ai_func)
  426.         {
  427.             /* call handle function with arg value */
  428.             arg_error_hfs = (*(ai->ai_func)) (param);
  429.             if (arg_error_hfs)
  430.                 set_argerr(ASE_HANDLE_FUNC, param);
  431.         }
  432.         else if (ai->ai_type == ARG_SWITCH)     /* switch */
  433.         {
  434.             *((BOOL *) dest) = TRUE;
  435.         }
  436.         else
  437.         {
  438.             /*
  439.              * check if argument already set by this set_args()
  440.              */
  441.             if ((ai->ai_set == AIS_SET_LOCAL)
  442.                 && !((ai->ai_flags & ARG_OVERWRITE)
  443.                      || (ai->ai_flags & ARG_MULTIPLE)))
  444.             {
  445.                 set_argerr(ASE_OCCURED_TWICE, arg);
  446.             }
  447.             else
  448.             {
  449.                 ai->ai_set = AIS_SET_LOCAL;
  450.             }
  451.  
  452.             if (no_argerr)
  453.             {
  454.                 APTR aparam = NULL;
  455.                 DLLIST **dest_list = (DLLIST **) dest;
  456.                 LONG along;
  457.  
  458.                 /*
  459.                  * get new value and  store it in aparam
  460.                  */
  461.                 if (!param)
  462.                 {
  463.                     /* missing param */
  464.                     set_argerr(ASE_NO_VAL_AFTER_KW, arg);
  465.                 }
  466.                 if (ai->ai_type == ARG_TEXT)
  467.                 {               /* text */
  468.                     aparam = (APTR) param;
  469.                 }
  470.                 else if (ai->ai_type == ARG_LONG)
  471.                 {               /* long */
  472.                     if (!str2long(param, &along))
  473.                         set_argerr(ASE_INVALID_NUM, arg);
  474.                     else
  475.                         aparam = (APTR) along;  /* what a pervert! */
  476.                 }
  477.                 else if (ai->ai_type == ARG_ENUM)
  478.                 {
  479.                     LONG aenum = strenum(param, ai->ai_misc1.ai_enum,
  480.                                          '|', STEN_NOCASE);
  481.  
  482.                     if (!aenum)
  483.                         set_argerr(ASE_INVALID_ENUM, arg);
  484.                     else
  485.                         aparam = (APTR) aenum;  /* what a pervert! */
  486.                 }
  487. #if 0
  488.                 if (!param)     /* missing param */
  489.                     set_argerr(ASE_NO_VAL_AFTER_KW, arg);
  490.                 if (ai->ai_type == ARG_TEXT)    /* text */
  491.                     *((STRPTR *) dest) = param;
  492.                 else if (ai->ai_type == ARG_LONG)
  493.                 {               /* long */
  494.                     if (!str2long(param, (LONG *) dest))
  495.                         set_argerr(ASE_INVALID_NUM, arg);
  496.                 }
  497. #endif
  498.  
  499.                 /*
  500.                  * set new value
  501.                  */
  502.                 if (no_argerr)
  503.                 {
  504.                     if (ai->ai_flags & ARG_MULTIPLE)
  505.                     {
  506.                         if (!(*dest_list))
  507.                             *dest_list = init_dllist(NULL);
  508.                         if (*dest_list)
  509.                         {
  510.                             if (!app_dlnode(*dest_list, aparam))
  511.                                 set_argerr(APE_NO_MEM, arg);
  512.                         }
  513.                         else
  514.                             set_argerr(APE_NO_MEM, arg);
  515.                     }
  516.                     else
  517.                     {
  518.                         if (ai->ai_type == ARG_LONG)
  519.                             *((LONG *) dest) = (LONG) aparam;
  520.                         else if (ai->ai_type == ARG_ENUM)
  521.                             *((LONG *) dest) = (LONG) aparam;
  522.                         else if (ai->ai_type == ARG_TEXT)
  523.                             *((STRPTR *) dest) = (STRPTR) aparam;
  524.  
  525.                     }
  526.                 }
  527.             }
  528.         }
  529.  
  530.         if (arg2used)           /* set return value that arg2 */
  531.             arg_incr = 1;       /* is skipped outside this func */
  532.     }
  533.  
  534.     return (arg_incr);
  535. }
  536.  
  537. /*
  538.  * check_required_set
  539.  *
  540.  * check, if all required arguments are set
  541.  *
  542.  */
  543. static VOID check_required_set(ARGLIST * al)
  544. {
  545.     DLNODE *nd = al->al_list->first;
  546.     ARGINFO *ai;
  547.  
  548.     do
  549.     {
  550.         ai = (struct arginfo *) dln_data(nd);
  551.  
  552.         if ((ai->ai_flags & ARG_REQUIRED) && (ai->ai_set == AIS_UNSET))
  553.             set_argerr(ASE_REQUIRED_MISS, ai->ai_id);
  554.         else
  555.             nd = dln_next(nd);
  556.     }
  557.     while (nd && no_argerr);
  558. }
  559.  
  560. /*
  561.  * set_args_file
  562.  *
  563.  * set args from argument file
  564.  */
  565. ARGFILE *new_argfile(char *argfname)
  566. {
  567. #define SIZE_FGETSBUF 1024
  568.     ARGFILE *argf = umalloc(sizeof(ARGFILE));
  569.  
  570.     BOOL no_argerr = TRUE;
  571.     if (argf)
  572.     {
  573.         FILE *file = NULL;
  574.  
  575.         argf->argc = 0;
  576.         argf->argv = umalloc(2 * sizeof(char *));
  577.         argf->argv[0] = NULL;
  578.         argf->argv[1] = NULL;
  579.  
  580.         if (argfname)
  581.         {
  582.             argf->argv[0] = strclone(argfname);
  583.             file = fopen(argfname, "r");
  584.         }
  585.         if (file)
  586.         {
  587.             STRPTR fgetsbuf = umalloc(SIZE_FGETSBUF);   /* alloc buf for fgets() */
  588.  
  589.             if (fgetsbuf)
  590.             {
  591.                 STRPTR argline = NULL;
  592.                 no_argerr = FALSE;
  593.  
  594.                 do
  595.                 {
  596.                     argline = fgets(fgetsbuf, SIZE_FGETSBUF, file);
  597.                     if (argline)
  598.                     {
  599.                         int i = 0;      /* loop var */
  600.  
  601.                         /* increse argv-array */
  602.                         char **old_argv = argf->argv;
  603.                         argf->argc++;
  604.                         argf->argv = umalloc((argf->argc + 2) * sizeof(char *));
  605.  
  606.                         /* copy old argv-array */
  607.                         for (i = 0; i <= (argf->argc); i++)
  608.                         {
  609.                             argf->argv[i] = old_argv[i];
  610.                         }
  611.  
  612.                         /* free old argv-array */
  613.                         ufree(old_argv);
  614.  
  615.                         /* strip succeeding linefeed */
  616.                         while (fgetsbuf[0]
  617.                                && strchr("\r\n", fgetsbuf[strlen(fgetsbuf) - 1]))
  618.                         {
  619.                             fgetsbuf[strlen(fgetsbuf) - 1] = '\0';
  620.                         }
  621.  
  622.                         /* assign new argv */
  623.                         argf->argv[argf->argc] = strclone(fgetsbuf);
  624.                         argf->argv[argf->argc + 1] = NULL;
  625.                     }
  626.                 }
  627.                 while (argline);
  628.                 argf->argc++;
  629.             }
  630.  
  631.             ufree(fgetsbuf);    /* cleanup resources */
  632.             fclose(file);
  633.         }
  634.     }
  635.  
  636.     return (argf);
  637. }
  638.  
  639. ARGFILE *new_argfilev(STRPTR fname[])
  640. {
  641.     int i=0;
  642.  
  643.     while(fname[i] && !fexists(fname[i]))
  644.     {
  645.         i++;
  646.     }
  647.  
  648.     return(new_argfile(fname[i]));
  649. }
  650.  
  651. /*
  652.  * del_argfile: release all resources allocated by new_argfile
  653.  */
  654. VOID del_argfile(ARGFILE * argf)
  655. {
  656.     if (argf)
  657.     {
  658.         while (argf->argc+1)
  659.         {
  660.             ufreestr(argf->argv[argf->argc]);
  661.             argf->argc--;
  662.         }
  663.         ufree(argf->argv);
  664.         ufree(argf);
  665.     }
  666. }
  667.  
  668. /*
  669.  * set_args_argv
  670.  *
  671.  * check and set arguments according to template specified in _al
  672.  *
  673.  * params: argc, argv[]...arguments from _main
  674.  *         al.............argument template (result from _prepare_args())
  675.  * result: TRUE, if no error occured
  676.  * errors: return FALSE, error information in _arg_error_???
  677.  *
  678.  */
  679. BOOL set_args_argv(int argc, char *argv[], ARGLIST * al)
  680. {
  681. #if 0
  682.     DA(fprintf(stderr, DUA "set_args()\n"));
  683. #endif
  684.     clr_argerr();
  685.     clr_ai_set(al);
  686.     reset_nokeywd(al);
  687.  
  688.     argidx = 1;
  689.  
  690.     if (al == NULL)
  691.         set_argerr(ASE_EMPTY_TEMPLATE, argv[argidx]);
  692.     else if (al->al_list == NULL)
  693.         set_argerr(ASE_EMPTY_TEMPLATE, argv[argidx]);
  694.  
  695.     while ((argidx < argc) && no_argerr)
  696.     {
  697.         struct arginfo search_ai;
  698.         struct arginfo *found_ai;
  699.         struct dlnode *ainode;
  700.         STRPTR arg2 = NULL;     /* passed to set_arg_value */
  701.         STRARR sas_c_is_buggy[20];
  702.  
  703.         /*
  704.          * search for entry in arginfo-list
  705.          */
  706.         search_ai.ai_id = argv[argidx];
  707.         ainode = find_dlnode(al->al_list->first, &search_ai, compare_arginfo);
  708.  
  709.         /* evaluate next argument (passed to set_arg_value) */
  710.         /* TODO: check if "<" or "<=" */
  711.         if (argidx < argc - 1)
  712.             arg2 = argv[argidx + 1];
  713.  
  714.         DA(fprintf(stderr, DUA "  arg: `%s'\n", argv[argidx]));
  715.  
  716.         /* this line compensates a bug in sas/c 6.51 optimizer */
  717.         strncpy(sas_c_is_buggy, argv[argidx], 20);
  718.  
  719.         if (ainode)
  720.         {
  721.             found_ai = (struct arginfo *) ainode->data;
  722.             argidx += set_arg_value(found_ai, argv[argidx], arg2, TRUE);
  723.         }
  724.         else
  725.         {
  726.             find_nxt_nokeywd(al);
  727.             if (al->al_nokeywd)
  728.             {
  729.                 argidx += set_arg_value(al->al_nokeywd, argv[argidx], arg2, FALSE);
  730.             }
  731.             else
  732.             {
  733.                 set_argerr(ASE_UNKNOWN_KEYWORD, argv[argidx]);
  734. #if 0
  735.                 DA(fprintf(stderr, DUA "  unknown keyword\n"));
  736. #endif
  737.             }
  738.         }
  739.  
  740.         argidx++;
  741.     }                           /* while */
  742.  
  743.     /* mark all arguments that have been set locally
  744.      * (with ai_set==AIS_SET_LOCAL) as set */
  745.     if (no_argerr)
  746.     {
  747.         DLNODE *nd = dll_first(al->al_list);
  748.         while (nd)
  749.         {
  750.             ARGINFO *ai = (struct arginfo *) dln_data(nd);
  751.             if (ai->ai_set == AIS_SET_LOCAL)
  752.                 ai->ai_set = AIS_SET_PREVIOUS;
  753.             nd = dln_next(nd);
  754.         }
  755.     }
  756.  
  757.     return no_argerr;
  758. }
  759.  
  760. /*
  761.  * check_args
  762.  *
  763.  * check for required args missing
  764.  */
  765. BOOL check_args(ARGLIST * al)
  766. {
  767.     /* check, if all required arguments were set */
  768.     if (no_argerr)
  769.     {
  770.         check_required_set(al);
  771.     }
  772.  
  773.     return no_argerr;
  774. }
  775.  
  776. /*
  777.  * set_args
  778.  *
  779.  * set and check args from arg-vector
  780.  */
  781. BOOL set_args(int argc, char *argv[], ARGLIST * al)
  782. {
  783.     return( (BOOL)(set_args_argv(argc,argv,al) && check_args(al)));
  784. }
  785.  
  786. /*
  787.  * set_args_file
  788.  *
  789.  * set args read from file
  790.  */
  791. BOOL set_args_file(ARGFILE *argf, ARGLIST *argl)
  792. {
  793.     return(set_args((argf)->argc, (argf)->argv, argl));
  794. }
  795.  
  796.  
  797.